﻿using DataTurnClient.Interface;
using DataTurnClient.Model;
using DataTurnClient.Server;
using DynamicData;
using Newtonsoft.Json;
using ReactiveUI;
using Splat;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Windows.Forms;

namespace DataTurnClient.ViewModel
{
    public class MainTurnViewModel : ReactiveObject
    {
        public ViewModelActivator Activator { get; }

        public IScheduler MainScheduler;


        #region 绑定视图
        /// <summary>
        /// 任务列表
        /// </summary>
        public BindingList<Job> JobList { get; set; } = new BindingList<Job>();
        /// <summary>
        /// 日志列表
        /// </summary>
        public BindingList<Log> LogList { get; set; } = new BindingList<Log>();

        /// <summary>
        /// 设置列表
        /// </summary>
        public BindingList<Setting> SetList { get; set; } = new BindingList<Setting>();

        public BindingList<RouteLine> RouteList { get; set; } = new BindingList<RouteLine>();

        public BindingList<string> CheckRouteList { get; set; } = new BindingList<string>();

        public BindingList<string> SelectList { get; set; } = new BindingList<string>();

        public BindingList<Job> AddJobList { get; set; } = new BindingList<Job>();

        #endregion

        #region 页面属性
        /// <summary>
        /// 同步任务定时器
        /// </summary>
        public System.Timers.Timer Timer { get; set; } = new System.Timers.Timer();


        public bool IsTimer
        {
            get => _IsTimer;
            set => this.RaiseAndSetIfChanged(ref _IsTimer, value);
        }
        private bool _IsTimer;

        /// <summary>
        /// 当前时间
        /// </summary>
        public List<string> NewTime
        {
            get => DateTime.Now.ToString("HH-mm-ss").Split('-').ToList();
        }

        public string JobTimeString
        {
            get => _JobTimeString;
            set =>  this.RaiseAndSetIfChanged(ref _JobTimeString, value); 
        }
        private string _JobTimeString;

        public Job CreateJob
        {
            get => _CreateJob;
            set => this.RaiseAndSetIfChanged(ref _CreateJob, value);
        }
        private Job _CreateJob = new Job();
        #endregion

        #region 添加属性


        #endregion

        #region Command方法
        public ReactiveCommand<Unit, Unit> SelectJobCommand { get; }

        public ReactiveCommand<Unit, Unit> SelectSetCommand { get; }

        public ReactiveCommand<string, Unit> RunJobCommand { get; }

        public ReactiveCommand<Unit, Unit> RunAllJobCommand { get; }

        public ReactiveCommand<string, Unit> ChangeJobStatusCommand { get; }

        public ReactiveCommand<Unit, Unit> IsRunTimeCommand { get; }

        public ReactiveCommand<Unit, Unit> ClearLogGridCommand { get; }

        public ReactiveCommand< string, string> ShowJobMessageCommand { get; }

        public ReactiveCommand<int, string> ShowLogMessageCommand { get; }

        public ReactiveCommand<string, Unit> AddLogCommand { get; }

        public ReactiveCommand<Job, Result<int>> AddJobCommand { get; }

        public ReactiveCommand<Job, Result<int>> UpdateJobCommand { get; }

        public ReactiveCommand<string, Result<Job>> SelectOneJobCommand { get; }

        public ReactiveCommand<string, bool> CheckControlCommand { get; }

        #endregion

        public List<Setting> BackUpSetting { get; set; } = new List<Setting>() 
        {
            new Setting()
            {
                Id = 1,
                SetGroup = "Base",
                SetName = "Timer",
                SetValue = "60000",
                SetDetail = "设置定时器"
            },
            new Setting()
            {
                Id = 2,
                SetGroup = "Base",
                SetName = "Log",
                SetValue = "100",
                SetDetail = "日志界面最大条数"
            },
            new Setting()
            {
                Id = 3,
                SetGroup = "Base",
                SetName = "Run",
                SetValue = "1",
                SetDetail = "是否默认打开即计时"
            },
            new Setting()
            {
                Id = 4,
                SetGroup = "DingSet",
                SetName = "On",
                SetValue = "0",
                SetDetail = "是否打开钉钉通知"

            },
            new Setting()
            {
                Id = 5,
                SetGroup = "DingSet",
                SetName = "Url",
                SetValue = "",
                SetDetail = "钉钉机器人链接"

            },
            new Setting()
            {
                Id = 6,
                SetGroup = "DingSet",
                SetName = "SafeCode",
                SetValue = "",
                SetDetail = "钉钉机器人设置的安全口令"

            },
        };



        //查询任务

        public MainTurnViewModel(IScheduler mainScheduler)
        {
            Activator = new ViewModelActivator();
            SelectJobCommand = ReactiveCommand.Create(SelectJobCommandImpl);
            SelectSetCommand = ReactiveCommand.Create(SelectSetCommandImpl);
            RunJobCommand = ReactiveCommand.Create<string>(RunJobCommandImpl);
            RunAllJobCommand = ReactiveCommand.Create(RunAllJobCommandImpl);
            ChangeJobStatusCommand = ReactiveCommand.Create<string>(ChangeJobStatusCommandImpl);
            IsRunTimeCommand = ReactiveCommand.Create(IsRunTimeCommandImpl);
            ClearLogGridCommand = ReactiveCommand.Create(ClearLogGridCommandImpl);
            ShowJobMessageCommand = ReactiveCommand.Create<string,string>(ShowJobMessageCommandImpl);
            ShowLogMessageCommand = ReactiveCommand.Create<int,string>(ShowLogMessageCommandImpl);
            AddLogCommand = ReactiveCommand.Create<string>(AddLogCommandImpl);
            AddJobCommand = ReactiveCommand.Create<Job, Result<int>>(AddJobCommandImpl);
            UpdateJobCommand = ReactiveCommand.Create<Job, Result<int>>(UpdateJobCommandImpl);
            SelectOneJobCommand = ReactiveCommand.Create<string, Result<Job>>(SelectOneJobCommandImpl);


            CheckControlCommand = ReactiveCommand.Create<string,bool>(CheckControlCommandImpl);
        }

        private void SelectJobCommandImpl()
        {
            try
            {
                var service = Locator.Current.GetService<IDBHelperService>();
                using (var db = service.SqlSugarClient(Globals.DbConnect, Globals.DbType))
                {
                    service.DataCodeCopy<Job>(db);
                    var DbJobList = db.Queryable<Job>().ToList();
                    if (DbJobList != null && DbJobList.Count > 0)
                    {
                        foreach (var jobItem in DbJobList)
                        {
                            var isJob = JobList.Where(x => x.JobCode == jobItem.JobCode).FirstOrDefault();
                            if (isJob == null)
                            {
                                jobItem.JobRunStatus = Job.JobRunType.Wating;
                                JobList.Add(jobItem);
                                SelectList.Add(jobItem.JobCode + "-" + jobItem.JobName);
                            }
                            else
                            {
                                isJob.JobRunStatus = isJob.JobRunStatus == Job.JobRunType.Run ? Job.JobRunType.Run : Job.JobRunType.Wating;
                                isJob.JobName = jobItem.JobName;
                                isJob.JobStatus = jobItem.JobStatus;
                                isJob.JobRunTime = jobItem.JobRunTime;
                                isJob.JobWeek = jobItem.JobWeek;
                                isJob.JobRoute = jobItem.JobRoute;
                                isJob.JobDetail = jobItem.JobDetail;
                                isJob.JobMode = jobItem.JobMode;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                var service = Locator.Current.GetService<ITool>();
                service.AddLog(ex.Message);
            }
        }

        private void SelectSetCommandImpl()
        {
            try
            {
                var tool = Locator.Current.GetService<ITool>();
                var service = Locator.Current.GetService<IDBHelperService>();
                using (var db = service.SqlSugarClient(Globals.DbConnect, Globals.DbType))
                {
                    service.DataCodeCopy<Setting>(db);
                    var Setting = db.Queryable<Setting>().ToList();
                    if (Setting != null && Setting.Count > 0)
                    {
                        foreach (var item in Setting)
                        {
                            var Set = SetList.Where(x => x.SetName == item.SetName).ToList().FirstOrDefault();
                            if (Set == null)
                            {
                                SetList.Add(item);
                            }
                        }
                        foreach (var item in Setting)
                        {
                            var Set = SetList.Where(x => x.SetName == item.SetName).ToList().FirstOrDefault();

                            if (Set.SetName == "Timer")
                            {
                                Globals.Base_Timer = Convert.ToInt32(Set.SetValue);
                            }
                            if (Set.SetName == "Log")
                            {
                                Globals.Base_Log = Convert.ToInt32(Set.SetValue);
                            }
                            if (Set.SetName == "Run")
                            {
                                Globals.Base_Run = Convert.ToInt32(Set.SetValue);
                            }
                            if (Set.SetName == "On")
                            {
                                Globals.DingSet_On = Convert.ToInt32(Set.SetValue);
                            }
                            if (Set.SetName == "Url")
                            {
                                Globals.DingSet_Url = Set.SetValue;
                            }
                            if (Set.SetName == "SafeCode")
                            {
                                Globals.DingSet_SafeCode = Set.SetValue;
                            }
                            Set.SetGroup = item.SetGroup;
                            Set.SetValue = item.SetValue;
                            Set.SetDetail = item.SetDetail;
                        }
                        var Route = db.Queryable<RouteLine>().ToList();
                        foreach (var route in Route)
                        {
                            var Set = RouteList.Where(x => x.Id == route.Id).ToList().FirstOrDefault();
                            if (Set == null)
                            {
                                RouteList.Add(route);
                                CheckRouteList.Add(route.Id + "-" + route.Ip + "-" + route.Port);
                            }
                            else
                            {
                                Set.Ip = route.Ip;
                                Set.Port = route.Port;
                                Set.Path = route.Path;
                            }
                        }
                    }
                    else 
                    {
                        db.Insertable<Setting>(BackUpSetting);
                    }
                }
            }
            catch (Exception ex)
            {
                var service = Locator.Current.GetService<ITool>();
                service.AddLog(ex.Message);
            }
        }

        private void RunJobCommandImpl(string JobCode)
        {
            var job = JobList.Where(x => x.JobCode == JobCode).FirstOrDefault();
            var server = Locator.Current.GetService<ITool>();
            AddLogCommand.Execute($"执行任务{JobCode}").Subscribe();
            job.JobRunStatus = Job.JobRunType.Run;
            Func<List<Job>, List<RouteLine>, string, Result<string>> myFunc = new Func<List<Job>, List<RouteLine>, string, Result<string>>(server.Execute);
            AsyncCallback myCallBack = GetResult;
            myFunc.BeginInvoke(JobList.ToList(), RouteList.ToList(), job.JobCode, myCallBack, myFunc);            
        }

        private void RunAllJobCommandImpl()
        {
            var logserver = Locator.Current.GetService<ITool>();
            logserver.WriterText("head ", DateTime.Now.ToString("HH-mm-ss") + "      所有任务运行");
            AddLogCommand.Execute($"点击运行所有任务").Subscribe();
            var job = JobList.Where(x => x.JobStatus == 1 && x.JobRunStatus != Job.JobRunType.Run).ToList();
            if (job.Count > 0)
            {
                foreach (var jobs in job)
                {
                    RunJobCommandImpl(jobs.JobCode);
                }
            }
            else
            {
                //AddLog("任务列表为空");
            }
        }

        private void ChangeJobStatusCommandImpl(string JobCode)
        {
            var job = JobList.Where(x => x.JobCode == JobCode).FirstOrDefault();
            int isRun = job.JobStatus == 0 ? 1 : 0;
            var server = Locator.Current.GetService<IDBHelperService>();
            using (var db = server.SqlSugarClient(Globals.DbConnect, Globals.DbType))
            {
                var results = db.Updateable<Job>()
                                            .SetColumns(it =>  new Job() {  JobStatus = isRun } )
                                            .Where(it => it.JobCode == job.JobCode).ExecuteCommand();
                job.JobStatus = results == 1 ? isRun : job.JobStatus;
                AddLogCommand.Execute($"{JobCode} 更改运行状态为：{job.JobStatus}").Subscribe();
            }
            var logserver = Locator.Current.GetService<ITool>();
            logserver.WriterText("update ", DateTime.Now.ToString("HH-mm-ss") + "      " + JsonConvert.SerializeObject(job));
        }

        private void IsRunTimeCommandImpl()
        {
            if (IsTimer)
            {
                var job = JobList.Where(x => x.JobStatus == 1).ToList();
                if (job.Count > 0)
                {
                    var service = Locator.Current.GetService<ITool>();
                    foreach (var jobs in job)
                    {
                        if (service.IsTime(jobs.Times, NewTime) && service.IsWeek(jobs.JobWeek))
                        {
                            var server = Locator.Current.GetService<ITool>();
                            RunJobCommandImpl(jobs.JobCode);
                            server.WriterText("Time ", DateTime.Now.ToString("HH-mm-ss") + "      " + JsonConvert.SerializeObject(jobs));
                        }
                    }
                }
                else
                {
                    //AddLog("任务列表为空");
                }
            }
        }

        private void ClearLogGridCommandImpl()
        {
            LogList.Clear();
        }

        private string ShowJobMessageCommandImpl(string JobCode)
        {
            var server = Locator.Current.GetService<ITool>();
            var job = JobList.Where(x => x.JobCode == JobCode).FirstOrDefault();
            return server.MsgShow(job);
        }

        private string ShowLogMessageCommandImpl(int index)
        {
            var server = Locator.Current.GetService<ITool>();
            var log = LogList[index];
            return server.LogShow(log);
        }

        private void GetResult(IAsyncResult ar)
        {
            Func<List<Job>, List<RouteLine>, string, Result<string>> func = (Func<List<Job>, List<RouteLine>, string, Result<string>>)ar.AsyncState;
            Result<string> ss = func.EndInvoke(ar);
             AddLogCommand.Execute(JsonConvert.SerializeObject(ss)).Subscribe();
        }

        private void AddLogCommandImpl(string content)
        {
            if (SetList.Count == 0)
            {
                SelectSetCommand.Execute().Subscribe();
            }
            LogList.Append(new Log
            {
                HappenTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                HappenDtal = content
            });
            Console.WriteLine(Globals.Base_Log);
            if (LogList.Count > Globals.Base_Log )
            {
                if (LogList[0] != null)
                {
                    LogList.RemoveAt(0);
                }
            }
            if (Globals.DingSet_On == 1)
            {
                ///钉钉发送
                DingSend.MsgSend(
                    Globals.DingSet_Url,
                    Globals.DingSet_SafeCode,
                    content);
            }
        }

        private Result<int> AddJobCommandImpl(Job job)
        {
            Result<int> result = new Result<int>()
            {
                Code = 200,
                Message = "请求成功",
                Success = true
            };
            try
            {
                var service = Locator.Current.GetService<IDBHelperService>();
                using (var db = service.SqlSugarClient(Globals.DbConnect, Globals.DbType))
                {
                    result.Data = db.Insertable(job).ExecuteCommand();
                }
            }
            catch (Exception ex)
            {
                result.Code = 500;
                result.Message = $"AddJobCommandImpl 发生异常：{ex.Message}";
                result.Success = false;
            }
            return result;
        }

        public Result<int>UpdateJobCommandImpl(Job job)
        {
            Result<int> result = new Result<int>()
            {
                Code = 200,
                Message = "请求成功",
                Success = true
            };
            try
            {
                var service = Locator.Current.GetService<IDBHelperService>();
                using (var db = service.SqlSugarClient(Globals.DbConnect, Globals.DbType))
                {
                    result.Data = db.Updateable(job).Where(x => x.JobCode == job.JobCode).ExecuteCommand();
                }
            }
            catch (Exception ex)
            {
                result.Code = 500;
                result.Message = $"UpdateJobCommandImpl 发生异常：{ex.Message}";
                result.Success = false;
            }
            return result;
        }

        public Result<Job> SelectOneJobCommandImpl(string JobCode)
        {
            Result<Job> result = new Result<Job>()
            {
                Code = 200,
                Message = "请求成功",
                Success = true
            };
            try
            {
                var service = Locator.Current.GetService<IDBHelperService>();
                using (var db = service.SqlSugarClient(Globals.DbConnect, Globals.DbType))
                {
                    result.Data = db.Queryable<Job>().Where(x => x.JobCode == JobCode).ToList().FirstOrDefault();
                }
            }
            catch (Exception ex)
            {
                result.Code = 500;
                result.Message = $"SelectOneJobCommandImpl 发生异常：{ex.Message}";
                result.Success = false;
            }
            return result;

        }

        private Result<Setting> GetSetValueCommandImpl(string setName)
        {
            Result<Setting> result = new Result<Setting>()
            {
                Code = 200,
                Message = "请求成功",
                Success = true
            };
            if (SetList.Where(x => x.SetName == setName).ToList() == null)
            {
                result.Code = 500;
                result.Message = $"无此项{setName}";
                result.Success = false;
            }
            else
            {
                result.Data = SetList.Where(x => x.SetName == setName).ToList().FirstOrDefault();
            }
            return result;
        }

        #region 控件方法
        private bool CheckControlCommandImpl(string Data)
        {
            if (Data != null && Data != "")
            {
                return false;
            }
            return true;
        }

        #endregion
    }
}
